from .models import *
from apps.product.models import GoodsBlockChain
from django.db import transaction
from apps.user.models import *
from apps.message.views import *
from sdks.getui import GetuiClient
from apps.mix import tasks


class BaseFlow(object):
    def __init__(self, obj):
        self.obj = obj


class OrderFlow(BaseFlow):
    """ Order Flow"""

    def __init__(self, obj):
        super().__init__(obj)

    def pre_sale_buy_update_users_info(self, order, tea_weight):
        """
        预售购买成功后更新用户信息
        用户藏茶量
        用户成长值
        """
        sub_orders = SubOrder.objects.filter(order=order)
        buyer_user = User.objects.get(pk=order.buyer_user_id)

        # 更新买家信息
        buyer_user.goods_block_count += len(sub_orders)
        # 更新成长值
        geted_grow_coins = int(tea_weight / 100) * getattr(GrowCoinRecord.Amount,
                                                           GrowCoinRecord.HappenType.TUN.name).value
        gcr = GrowCoinRecord.objects.create(user=buyer_user,
                                            happen_type=GrowCoinRecord.HappenType.TUN.name,
                                            amount=geted_grow_coins)
        buyer_user.grow_coin += gcr.amount
        buyer_user.save()
        buyer_user.current_tun_level()

    def market_buy_update_users_info(self, order, tea_weight, old_trade_price, new_trade_price):
        sub_orders = SubOrder.objects.filter(order=order)
        first_sub_order = sub_orders.first()
        buyer_user = User.objects.get(pk=order.buyer_user_id)
        seller_user = User.objects.get(pk=first_sub_order.seller_user_id)
        market_order = MarketOrder.objects.filter(id=first_sub_order.market_order_id).first()

        if GrowCoinRecord.is_grow_record(buyer_user.id, market_order):
            # 更新买家信息
            buyer_user.goods_block_count += len(sub_orders)
            # 更新成长值
            # 囤茶获取成长值
            tun_geted_grow_coins = int(tea_weight / 100) * getattr(GrowCoinRecord.Amount,
                                                                   GrowCoinRecord.HappenType.TUN.name).value
            tun_gcr = GrowCoinRecord.objects.create(user=buyer_user,
                                                    happen_type=GrowCoinRecord.HappenType.TUN.name,
                                                    amount=tun_geted_grow_coins)
            buyer_user.grow_coin += tun_gcr.amount
            # 交易获取成长值
            buyer_trade_geted_grow_coins = getattr(GrowCoinRecord.Amount, GrowCoinRecord.HappenType.TRADE.name).value
            buyer_trade_gcr = GrowCoinRecord.objects.create(
                user=buyer_user, happen_type=GrowCoinRecord.HappenType.TRADE.name, amount=buyer_trade_geted_grow_coins
            )
            buyer_user.grow_coin += buyer_trade_gcr.amount
            buyer_user.save()
            buyer_user.current_tun_level()

        if GrowCoinRecord.is_grow_record(seller_user.id, market_order):
            # 更新卖家信息(持仓量)
            seller_user.goods_block_count -= len(sub_orders)
            # 更新成长值
            # 交易成长值
            seller_trade_geted_grow_coins = getattr(GrowCoinRecord.Amount, GrowCoinRecord.HappenType.TRADE.name).value
            seller_trade_gcr = GrowCoinRecord.objects.create(
                user=seller_user, happen_type=GrowCoinRecord.HappenType.TRADE.name, amount=seller_trade_geted_grow_coins
            )
            seller_user.grow_coin += seller_trade_gcr.amount
            # 判断挂单价和囤茶价倍数
            if old_trade_price == Decimal('0.00'):
                pass
            else:
                multi_n = int(new_trade_price / old_trade_price)
                if multi_n > 0:
                    seller_trade_price_geted_grow_coins = getattr(GrowCoinRecord.Amount,
                                                                  GrowCoinRecord.HappenType.MO_MULTI_PRICE.name).value * multi_n
                    seller_trade_price_gcr = GrowCoinRecord.objects.create(
                        user=seller_user, happen_type=GrowCoinRecord.HappenType.MO_MULTI_PRICE.name,
                        amount=seller_trade_price_geted_grow_coins
                    )
                    seller_user.grow_coin += seller_trade_price_gcr.amount
            seller_user.save()
            seller_user.current_tun_level()

    def take_out_update_users_info(self, order):
        buyer_user = User.objects.get(pk=order.buyer_user_id)
        buyer_user.goods_block_count -= SubOrder.objects.filter(order=order).count()
        buyer_user.save()

    def post_trade_order_finished(self):
        """
        订单完成后操作
        """
        from apps.product.models import GoodsBlock, MarketOrder
        from apps.user.models import User
        from apps.repo.models import Repo, StoreUnitThree
        from decimal import Decimal
        order = self.obj
        order.status = Order.Status.FINISHED.name
        order.save()
        import datetime as dt
        if order.post_finished_done:
            return None
        # 查询遍历子订单， 操作区块
        sub_orders = SubOrder.objects.filter(order=order)
        first_sub_order = sub_orders.first()
        product = Product.objects.get(pk=first_sub_order.product_id)
        seller_market_order = MarketOrder.objects.filter(id=first_sub_order.market_order_id).first()
        first_sub_order_goods_block = GoodsBlock.objects.get(pk=first_sub_order.goods_block_id)

        tea_weight = 0
        old_trade_price = first_sub_order_goods_block.trade_price
        new_trade_price = first_sub_order.amount

        with transaction.atomic():
            transfer_gb_ids = []

            if first_sub_order.create_type == SubOrder.CreateType.PRE_SALE_BUY_IN.name:
                tea_weight = sub_orders.count() * product.weight
                GoodsBlock.objects.filter(id__in=[so.goods_block_id for so in sub_orders]).update(
                    locked_by_user_id=None, locked_expire_at=0,
                    trade_datetime=dt.datetime.now(), owner_user_id=order.buyer_user_id,
                    trade_type=GoodsBlock.TradeType.PRE_SALE.name, trade_price=first_sub_order.amount,
                    repo_id=first_sub_order.goods_block_to_repo_id)


                oper_user = User.objects.filter(id=first_sub_order.seller_user_id).first()
                message_user_id = order.buyer_user_id
                product_name = first_sub_order.product_name
                order_id = order.id
                CreateMessageView.message(msg_type=Message.MsgType.GOT.name,
                                                oper_user=oper_user,
                                                message_user_id=message_user_id,
                                                product_name=product_name,
                                                order_id=order_id)
                gbcs = []
                for sub_order in sub_orders:
                    gbc = GoodsBlockChain.create_chain(
                        chain_type=GoodsBlockChain.ChainType.PRE_SALE_BUY_IN.name, goods_block=sub_order.goods_block_id,
                        order=order, sub_order=sub_order, save=False, repo_id=first_sub_order.goods_block_to_repo_id,
                        trade_price=first_sub_order.amount
                    )
                    gbcs.append(gbc)
                GoodsBlockChain.objects.bulk_create(gbcs)
                self.pre_sale_buy_update_users_info(order, tea_weight)

            else:
                for sub_order in sub_orders:
                    # 查询GoodsBlock
                    goods_block_id = sub_order.goods_block_id
                    goods_block = GoodsBlock.objects.get(pk=goods_block_id)

                    # 更新所有者
                    goods_block.owner_user_id = order.buyer_user_id
                    transfer_gb_ids.append(goods_block.id)
                    # 默认清理锁定信息
                    goods_block.locked_by_user_id = None
                    goods_block.locked_expire_at = 0
                    # 更新交易时间
                    if first_sub_order.create_type == SubOrder.CreateType.PRE_SALE_BUY_IN.name:
                        import datetime as dt
                        goods_block.trade_datetime = dt.datetime.now()
                    else:
                        goods_block.trade_datetime = sub_order.repo_cost_end_datetime
                    goods_block.save()

                    # 最高价和平均价
                    if seller_market_order and seller_market_order.intention_type == MarketOrder.IntentionType.SELL.name and seller_market_order.publish_type == MarketOrder.PublishType.MARKET.name:
                        if goods_block.trade_price > goods_block.product.max_price:
                            goods_block.product.max_price = goods_block.trade_price
                        goods_block.product.avg_price = goods_block.make_product_avg_price()
                        # 最后一次成交价
                        goods_block.product.last_trade_price = goods_block.trade_price
                        goods_block.product.up_down_percent = Decimal(
                            str((goods_block.product.last_trade_price - goods_block.product.pre_sale_price)
                                / goods_block.product.pre_sale_price))
                        goods_block.product.save()
                        # 保存当前均价
                        from apps.product.models import ProductAvgPrice
                        ProductAvgPrice.objects.create(product=goods_block.product, avg_price=goods_block.product.avg_price)

                    if first_sub_order.create_type == SubOrder.CreateType.PRE_SALE_BUY_IN.name:  # 预售买入
                        goods_block.trade_type = GoodsBlock.TradeType.PRE_SALE.name
                        # goods_block.product.keeping_count += 1
                        goods_block.product.save()
                    elif first_sub_order.create_type == SubOrder.CreateType.MARKET_BUY_IN.name:  # 茶市买入
                        goods_block.trade_type = GoodsBlock.TradeType.MARKET.name
                        goods_block.market_order = None
                    elif first_sub_order.create_type == SubOrder.CreateType.TAKE_OUT.name:  # 提仓
                        goods_block.trade_type = GoodsBlock.TradeType.TAKE_OUT.name
                        goods_block.market_order = None
                        goods_block.product.save()
                    goods_block.save()

                    if first_sub_order.create_type in [SubOrder.CreateType.PRE_SALE_BUY_IN.name,
                                                       SubOrder.CreateType.MARKET_BUY_IN.name]:
                        goods_block.trade_price = sub_order.amount
                        goods_block.avg_price = goods_block.get_avg_price()
                        # 更新区块存储单元
                        goods_block.repo_id = sub_order.goods_block_to_repo_id
                        goods_block.save()
                    elif first_sub_order.create_type == SubOrder.CreateType.TAKE_OUT.name:  #
                        # 释放存储单元
                        gb_store_unit = StoreUnitThree.objects.get(pk=goods_block.store_unit_id)
                        gb_store_unit.in_use = False
                        gb_store_unit.save()

                    # 更新区块链信息
                    if first_sub_order.create_type == SubOrder.CreateType.PRE_SALE_BUY_IN.name:  # 预售买入
                        # 预售买入入链
                        GoodsBlockChain.create_chain(
                            chain_type=GoodsBlockChain.ChainType.PRE_SALE_BUY_IN.name, goods_block=goods_block,
                            order=order, sub_order=sub_order, save=False
                        )
                        tea_weight += goods_block.product.weight
                    elif first_sub_order.create_type == SubOrder.CreateType.MARKET_BUY_IN.name:  # 茶市买入
                        # 更新MarketOrder信息
                        market_order = MarketOrder.objects.get(pk=sub_order.market_order_id)
                        market_order.status = MarketOrder.Status.END.name
                        market_order.save()
                        buyer_market_order = market_order.buy_in_market_order
                        if buyer_market_order:
                            buyer_market_order.status = MarketOrder.Status.END.name
                            buyer_market_order.save()

                        # 卖出节点
                        GoodsBlockChain.create_chain(
                            chain_type=GoodsBlockChain.ChainType.PUBLISH_SELL.name, goods_block=goods_block,
                            order=order, sub_order=sub_order
                        )
                        # 买入节点
                        GoodsBlockChain.create_chain(
                            chain_type=GoodsBlockChain.ChainType.MARKET.name, goods_block=goods_block,
                            order=order, sub_order=sub_order
                        )

                        tea_weight += goods_block.product.weight
                    elif first_sub_order.create_type == SubOrder.CreateType.TAKE_OUT.name:  # 提仓
                        # 更新MarketOrder信息
                        market_order = MarketOrder.objects.get(pk=sub_order.market_order_id)
                        market_order.status = MarketOrder.Status.END.name
                        market_order.save()

                # 检查是否需要拆单操作(仅卖出挂单有关联买入挂单时)
                if seller_market_order:
                    buyer_market_order = seller_market_order.buy_in_market_order
                    trade_count = SubOrder.objects.filter(market_order_id=seller_market_order.id).count()
                    if seller_market_order.count > trade_count:  # 卖出大于买入
                        # 修改卖出挂单，生成新卖出挂单
                        new_seller_market_order = MarketOrder.objects.create(
                            user_id=seller_market_order.user_id,
                            product=seller_market_order.product,
                            intention_type=seller_market_order.intention_type,
                            offered_price=seller_market_order.offered_price,
                            count=seller_market_order.count - trade_count,
                            publish_type=seller_market_order.publish_type,
                            status=MarketOrder.Status.ING.name,
                            as_gift=False,
                        )
                        GoodsBlock.objects.filter(~Q(id__in=transfer_gb_ids), market_order=seller_market_order).update(
                            market_order=new_seller_market_order)
                        #
                        seller_market_order.count = trade_count
                        seller_market_order.status = MarketOrder.Status.END.name
                        seller_market_order.save()
                        if buyer_market_order:
                            buyer_market_order.status = MarketOrder.Status.END.name
                            buyer_market_order.save()
                    elif buyer_market_order and seller_market_order.count < buyer_market_order.count:  # 卖出小于买入
                        # 修改买入挂单，生成新买入挂单
                        new_buyer_market_order = MarketOrder.objects.create(
                            user_id=buyer_market_order.user_id,
                            product=buyer_market_order.product,
                            intention_type=buyer_market_order.intention_type,
                            offered_price=buyer_market_order.offered_price,
                            count=buyer_market_order.count - seller_market_order.count,
                            publish_type=buyer_market_order.publish_type,
                            status=MarketOrder.Status.ING.name,
                            as_gift=False,
                        )
                        #
                        buyer_market_order.count = seller_market_order.count
                        buyer_market_order.status = MarketOrder.Status.END.name
                        buyer_market_order.save()
                        seller_market_order.status = MarketOrder.Status.ING.name
                        seller_market_order.save()
                        # 更新其他满足该条的挂单
                        MarketOrder.objects.filter(status=MarketOrder.Status.ING.name,
                                                   buy_in_market_order=buyer_market_order).update(
                            buy_in_market_order=new_buyer_market_order)

                if first_sub_order.create_type == SubOrder.CreateType.PRE_SALE_BUY_IN.name:  # 预售买入
                    self.pre_sale_buy_update_users_info(order, tea_weight)
                elif first_sub_order.create_type == SubOrder.CreateType.MARKET_BUY_IN.name:  # 茶市买入
                    self.market_buy_update_users_info(order, tea_weight, old_trade_price, new_trade_price)
                elif first_sub_order.create_type == SubOrder.CreateType.TAKE_OUT.name:  # 提仓
                    self.take_out_update_users_info(order)
                    order.status = Order.Status.PAYED.name
                    # 核销包邮次数
                    from apps.user.models import UserTunLevelRightTimes
                    urt = UserTunLevelRightTimes.objects.filter(pk=order.use_take_out_free_postage_right_id).first()
                    if urt:
                        urt.used = True
                        urt.save()
                    order.save()

                # 消息发送
                if first_sub_order.create_type == SubOrder.CreateType.PRE_SALE_BUY_IN.name:  # 预售买入
                    CreateMessageView.message(msg_type=Message.MsgType.GOT.name,
                                              oper_user=User.objects.filter(id=first_sub_order.seller_user_id).first(),
                                              message_user_id=order.buyer_user_id,
                                              product_name=first_sub_order.product_name,
                                              order_id=order.id)
                elif first_sub_order.create_type == SubOrder.CreateType.MARKET_BUY_IN.name:  # 茶市买入
                    # 买入消息
                    seller_user = User.objects.filter(id=first_sub_order.seller_user_id).first()
                    CreateMessageView.message(msg_type=Message.MsgType.GOT.name,
                                              oper_user=seller_user,
                                              message_user_id=order.buyer_user_id,
                                              product_name=first_sub_order.product_name,
                                              order_id=order.id,
                                              market_order_id=first_sub_order.market_order_id)
                    # 卖出消息
                    msg = CreateMessageView.message(msg_type=Message.MsgType.SOLD_OUT.name,
                                                    oper_user=User.objects.filter(id=order.buyer_user_id).first(),
                                                    message_user_id=first_sub_order.seller_user_id,
                                                    product_name=first_sub_order.product_name,
                                                    order_id=order.id,
                                                    market_order_id=first_sub_order.market_order_id)

                    t = tasks.task_send_transmission_msg.delay(user_id=seller_user.id,
                                                               transmission_msg_data=msg.make_transmission_msg(),
                                                               message_id=msg.pk, with_push=True)
                    from apps.mix.models import TaskProcess
                    TaskProcess.objects.create(task_callable="task_send_transmission_msg",
                                               task_name=tasks.task_send_transmission_msg.name, task_id=t.id)

                elif first_sub_order.create_type == SubOrder.CreateType.TAKE_OUT.name:  # 提仓
                    CreateMessageView.message(msg_type=Message.MsgType.TAKE_OUT.name,
                                              oper_user=User.objects.filter(id=first_sub_order.seller_user_id).first(),
                                              message_user_id=order.buyer_user_id,
                                              product_name=first_sub_order.product_name,
                                              order_id=order.id,
                                              market_order_id=first_sub_order.market_order_id)

            order.post_finished_done = True
            order.save()
